package com.taysear.parcel;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

import com.taysear.parcel.domain.Loadingsheet;
import com.taysear.parcel.domain.LoadingsheetAction;
import com.taysear.parcel.domain.LoadingsheetHistory;
import com.taysear.parcel.domain.LoadingsheetStatus;
import com.taysear.parcel.domain.Parcel;
import com.taysear.parcel.domain.ParcelAction;
import com.taysear.parcel.domain.ParcelHistory;
import com.taysear.parcel.domain.ParcelStatus;
import com.taysear.parcel.domain.Substation;
import com.taysear.parcel.domain.User;
import com.taysear.parcel.util.Constants;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.addon.jpacontainer.JPAContainerItem;
import com.vaadin.addon.tableexport.ExcelExport;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.filter.And;
import com.vaadin.data.util.filter.Compare.Equal;
import com.vaadin.data.util.filter.Between;
import com.vaadin.data.util.filter.Or;
import com.vaadin.event.dd.acceptcriteria.SourceIs;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.CustomLayout;
import com.vaadin.ui.DateField;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.Reindeer;

@SuppressWarnings("serial")
public class LoadingsheetWindow extends VerticalLayout {
	ParcelApplication app;
	MainLayout mainLayout;
	JPAContainer<Loadingsheet> loadingsheetsContainer;
	LoadingsheetTable loadingsheetTable;
	BeanItemContainer<Parcel> todaysNotLoadedParcelsContainer;
	BeanItemContainer<Parcel> todaysLoadedParcelsContainer;
	VerticalLayout notLoadedParcelsLayout;
	VerticalLayout loadedParcelsLayout;
	ParcelTable notLoadedParcelTable = null;
	ParcelTable loadedParcelTable = null;
	LoadingsheetForm form;
	Button saveLoadingsheetBtn;
	Button editBtn;
	Button deliverBtn;
	Button printBtn;
	Button historyBtn;
	Button exportBtn;
	Button showLoadingsheetParcelsBtn;
	Boolean isOutgoing;
	String direction;
	Integer selectedLoadingsheet;
	DateField date;
	String [] columnsLoadingsheetTable = new String[] {"Loadingsheet No", "RouteTime", "Origin", "Destination", "Date", "Reg No", "Driver", "Conductor", "Status"};
	List<String> columnsLoadingsheetForm = Arrays.asList(new String[] {"routeTime", "origin", "destination", "bus", "driver", "conductor"});
	String [] columnsNotLoadedParcelTable = new String[] {"Waybill No", "Sender", "Receiver", "Destination", "Status"};
    String [] columnsLoadedParcelTable = new String[] {"Waybill No", "Sender", "Receiver", "Destination", "Status", "Loadingsheet"};
	private Subject currentUser;

	public LoadingsheetWindow(final ParcelApplication app, MainLayout mainWindow, final Boolean isOutgoing) {
		this.app = app;
		this.mainLayout = mainWindow;
		this.isOutgoing = isOutgoing;
		this.currentUser = SecurityUtils.getSubject();
		
		CustomLayout loadingsheetWindowLayout = new CustomLayout("manageLoadingsheet");
		addComponent(loadingsheetWindowLayout);
		
		VerticalLayout searchLayout = new VerticalLayout();
		searchLayout.setSpacing(true);
		loadingsheetWindowLayout.addComponent(searchLayout, "form");
		
		loadingsheetsContainer = JPAContainerFactory.make(Loadingsheet.class, app.PERSISTENCE_UNIT);
		
		direction = isOutgoing ? "Outgoing" : "Incomming";
		String dr = isOutgoing ? "origin" : "destination";
		Equal sid = new Equal(dr+".substationId",app.getUser().getEmployee().getSubstation().getSubstationId());
		Date start = app.getStartOfADay(new Date());
		Date end = app.getEndOfADay(new Date());
		Between dateEqual = new Between("date", start, end);
		Equal statusNew = new Equal("loadingsheetStatus.loadingsheetStatusId", Constants.LOADINGSHEET_STATUS_NEW);
		Equal statusEdited = new Equal("loadingsheetStatus.loadingsheetStatusId", Constants.LOADINGSHEET_STATUS_EDITED);
		Equal statusLoaded = new Equal("loadingsheetStatus.loadingsheetStatusId", Constants.LOADINGSHEET_STATUS_LOADED);
		if(isOutgoing){
			loadingsheetsContainer.addContainerFilter(new And(sid, new Or(statusNew, statusEdited, statusLoaded)));
		} else{
			Equal statusDelivered = new Equal("loadingsheetStatus.loadingsheetStatusId", Constants.LOADINGSHEET_STATUS_DELIVERED);
			loadingsheetsContainer.addContainerFilter(new And(sid, statusLoaded));
		}
		loadingsheetTable = new LoadingsheetTable(app, direction+" loading sheets", loadingsheetsContainer, columnsLoadingsheetTable, this);
		
		date = new DateField("Date");
		date.setValue(new Date());
		date.setDateFormat(Constants.DATE_FORMAT_STRING);
		date.setResolution(DateField.RESOLUTION_DAY);
		
		Button search = new Button("Search");
		search.addStyleName("blueButton");
		search.setDisableOnClick(true);
		search.addListener(new ClickListener() {
            public void buttonClick(final ClickEvent event) {
            	notLoadedParcelsLayout.removeAllComponents();
        		loadedParcelsLayout.removeAllComponents();
        		saveLoadingsheetBtn.setVisible(false);
        		
            	searchLoadingsheet();
            	event.getButton().setEnabled(true);
            }
        });
		
		searchLayout.addComponent(date);
		searchLayout.addComponent(search);
		
		HorizontalLayout actionButtons = new HorizontalLayout();
		actionButtons.setSpacing(true);
		loadingsheetWindowLayout.addComponent(actionButtons, "actionButtons");
		
		if(isOutgoing){
			Button addBtn = new Button("Add");
			addBtn.addStyleName("greenButton");
			if (!currentUser.isPermitted(PermissionsConstants.PERMISSION_LOADINGSHEET_OUTGOING_CREATE))
				addBtn.setVisible(false);
			addBtn.setDisableOnClick(true);
			addBtn.addListener(new ClickListener() {
	            public void buttonClick(final ClickEvent event) {
	            	addLoadingsheetWindow();
	            	event.getButton().setEnabled(true);
	            }
	        });
					
			editBtn = new Button("Edit");
			editBtn.addStyleName("greenButton");
			editBtn.setEnabled(false);
			if (!currentUser.isPermitted(PermissionsConstants.PERMISSION_LOADINGSHEET_OUTGOING_EDIT))
				editBtn.setVisible(false);
			editBtn.setDisableOnClick(true);
			editBtn.addListener(new ClickListener() {
	            public void buttonClick(final ClickEvent event) {
	            	editLoadingsheetWindow();
	            	event.getButton().setEnabled(true);
	            }
	        });
			
			actionButtons.addComponent(addBtn);
			actionButtons.addComponent(editBtn);
			loadingsheetTable.addListener(new Table.ValueChangeListener() {
				@Override
				public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) {
                	enableEditButton();
	                enablePrintHistoryButtons();
	            }
	        });
		} else {
			deliverBtn = new Button("Deliver");
			deliverBtn.addStyleName("greenButton");
			deliverBtn.setEnabled(false);
			if (!currentUser.isPermitted(PermissionsConstants.PERMISSION_LOADINGSHEET_INCOMMING_DELIVER))
				deliverBtn.setVisible(false);
			deliverBtn.setDisableOnClick(true);
			deliverBtn.addListener(new ClickListener() {
	            public void buttonClick(final ClickEvent event) {
	            	if(loadingsheetTable.getValue() != null){
	            		selectedLoadingsheet = (Integer) loadingsheetTable.getValue();
	            		deliverParcelWindow(selectedLoadingsheet);
	            	}
	            	event.getButton().setEnabled(true);
	            }
	        });
			actionButtons.addComponent(deliverBtn);
			loadingsheetTable.addListener(new Table.ValueChangeListener() {
				@Override
				public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) {
	                if (loadingsheetTable.getValue() != null) {
	                	enableDeliverButton();
	                }
	                enablePrintHistoryButtons();
	            }
	        });
		}
		
		printBtn = new Button("Print");
		printBtn.addStyleName("greenButton");
		printBtn.setEnabled(false);
		if (!currentUser.isPermitted(PermissionsConstants.PERMISSION_LOADINGSHEET_PRINT))
			printBtn.setVisible(false);
		printBtn.setDisableOnClick(true);
		printBtn.addListener(new ClickListener() {
            public void buttonClick(final ClickEvent event) {
            	if(loadingsheetTable.getValue() != null){
            		Loadingsheet loadingsheet = app.em.find(Loadingsheet.class, loadingsheetTable.getValue());
            		getApplication().getMainWindow().addWindow(new PrintToPDF(app, loadingsheet));
            	}
            	event.getButton().setEnabled(true);
            }
        });
		
		actionButtons.addComponent(printBtn);
		
		exportBtn = new Button("Export");
		exportBtn.addStyleName("greenButton");
		exportBtn.setEnabled(false);
		exportBtn.setDisableOnClick(true);
		exportBtn.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
            	ExcelExport excelExport;
            	if(loadingsheetTable.getValue() != null){
            		final Loadingsheet loadingsheet = ((JPAContainerItem<Loadingsheet>) loadingsheetTable.getItem(loadingsheetTable.getValue())).getEntity();
            		String stationType = isOutgoing ? "senderStation" : "receiverStation";
            		BeanItemContainer<Parcel> todaysLoadedParcelsContainer = mainLayout.getParcelsByLoadingsheetId(stationType, loadingsheet.getLoadingsheetId());
            		String [] columnsExportParcelTable = new String[] {"Sender", "Sender Tel", "Receiver", "Receiver Tel"};
            		final ParcelTable table = new ParcelTable(app, "Parcels", todaysLoadedParcelsContainer, columnsExportParcelTable, loadingsheet.getLoadingsheetId());
	            	
            		Button export = new Button("Export");
            		export.addStyleName("greenButton");
            		export.setDisableOnClick(true);
            		export.addListener(new Button.ClickListener() {
                        public void buttonClick(ClickEvent event) {
                        	ExcelExport excelExport = new ExcelExport(table);
                            excelExport.setExportFileName("loadingsheet.xls");
                            excelExport.setDisplayTotals(false);
                            excelExport.export();
                            event.getButton().setEnabled(true);

                        }
                    });
                    
                    Window editWindow = new Window("Export loadingsheet parcels");
	    	    	editWindow.center();
	    	    	editWindow.setModal(true);
	    			VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
	    			verticalLayout.setMargin(true);
	    	        verticalLayout.setSpacing(true);
	    			verticalLayout.setSizeUndefined();
	    			verticalLayout.addComponent(export);
	    			verticalLayout.setComponentAlignment(export, Alignment.MIDDLE_RIGHT);
	    	    	verticalLayout.addComponent(table);
	    	    	getApplication().getMainWindow().addWindow(editWindow);
            	}
            }
        });
		actionButtons.addComponent(exportBtn);
		
		historyBtn = new Button("History");
		historyBtn.addStyleName("greenButton");
		historyBtn.setEnabled(false);
		historyBtn.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
            	if(loadingsheetTable.getValue() != null){
	            	JPAContainer<LoadingsheetHistory> container = JPAContainerFactory.make(LoadingsheetHistory.class, app.PERSISTENCE_UNIT);
	            	container.addContainerFilter(new Equal("loadingsheet.loadingsheetId", loadingsheetTable.getValue()));
	            	String [] columns = new String[] {"Date", "User", "Action", "Description"};
	            	LoadingsheetHistoryTable table = new LoadingsheetHistoryTable(app, container, columns);
	            	
	            	Window editWindow = new Window("Loadingsheet history");
	    	    	editWindow.center();
	    	    	editWindow.setModal(true);
	    			VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
	    			verticalLayout.setMargin(true);
	    	        verticalLayout.setSpacing(true);
	    			verticalLayout.setSizeUndefined();
	    	    	verticalLayout.addComponent(table);
	    	    	getApplication().getMainWindow().addWindow(editWindow);
            	}
            }
        });
		actionButtons.addComponent(historyBtn);
		
		showLoadingsheetParcelsBtn = new Button("Show parcels");
		showLoadingsheetParcelsBtn.addStyleName("blueButton");
		showLoadingsheetParcelsBtn.setEnabled(false);
		showLoadingsheetParcelsBtn.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
            	if(loadingsheetTable.getValue() != null) {
            		Loadingsheet loadingsheet = ((JPAContainerItem<Loadingsheet>) loadingsheetTable.getItem(loadingsheetTable.getValue())).getEntity();
	            	
            		selectedLoadingsheet = (Integer)loadingsheetTable.getValue();
                	showParcelTables(selectedLoadingsheet);
            		
	            	Window editWindow = new Window("Parcels for "+ loadingsheet.getRouteTime());
	            	
	            	HorizontalLayout parcelsLayout = new HorizontalLayout();
	        		parcelsLayout.setSizeFull();
	        		parcelsLayout.setSpacing(true);
	        		parcelsLayout.addComponent(notLoadedParcelsLayout);
	        		parcelsLayout.addComponent(loadedParcelsLayout);
	        		parcelsLayout.addComponent(saveLoadingsheetBtn);
	        		
	            	
	    	    	editWindow.center();
	    	    	editWindow.setModal(true);
	    			VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
	    			verticalLayout.setMargin(true);
	    	        verticalLayout.setSpacing(true);
	    			verticalLayout.setSizeUndefined();
	    	    	verticalLayout.addComponent(parcelsLayout);
	    	    	getApplication().getMainWindow().addWindow(editWindow);
            	}
            }
        });
		actionButtons.addComponent(showLoadingsheetParcelsBtn);
		searchLayout.addComponent(actionButtons);
		
		loadingsheetWindowLayout.addComponent(loadingsheetTable, "result");
		
		notLoadedParcelsLayout = new VerticalLayout();
		loadedParcelsLayout = new VerticalLayout();
		
		saveLoadingsheetBtn = saveLoadingsheetButton();
		saveLoadingsheetBtn.addStyleName("blueButton");
		saveLoadingsheetBtn.setDisableOnClick(true);
		saveLoadingsheetBtn.setVisible(false);
	}
	
	private void enableEditButton(){
		if(loadingsheetTable.getValue() != null) {
			Loadingsheet loadingsheet = ((JPAContainerItem<Loadingsheet>) loadingsheetTable.getItem(loadingsheetTable.getValue())).getEntity();
			int status = loadingsheet.getLoadingsheetStatus().getLoadingsheetStatusId();
			if(status == Constants.LOADINGSHEET_STATUS_NEW | status == Constants.LOADINGSHEET_STATUS_EDITED)
				editBtn.setEnabled(true);
			else 
				editBtn.setEnabled(false);
		} else {
			editBtn.setEnabled(false);
		}
	}
	
	private void enablePrintHistoryButtons(){
		if(loadingsheetTable.getValue() != null){
			printBtn.setEnabled(true);
			historyBtn.setEnabled(true);
			exportBtn.setEnabled(true);
			showLoadingsheetParcelsBtn.setEnabled(true);
			deliverBtn.setEnabled(true);
		} else{ 
			printBtn.setEnabled(false);
			historyBtn.setEnabled(false);
			exportBtn.setEnabled(false);
			showLoadingsheetParcelsBtn.setEnabled(false);
			deliverBtn.setEnabled(false);
		}
	}
	
	private void enableDeliverButton(){
		Loadingsheet loadingsheet = ((JPAContainerItem<Loadingsheet>) loadingsheetTable.getItem(loadingsheetTable.getValue())).getEntity();
		int status = loadingsheet.getLoadingsheetStatus().getLoadingsheetStatusId();
		if(status == Constants.LOADINGSHEET_STATUS_LOADED)
			deliverBtn.setEnabled(true);
		else 
			deliverBtn.setEnabled(false);
	}
	
	protected void searchLoadingsheet(){
		
		JPAContainer<Loadingsheet> container = JPAContainerFactory.make(Loadingsheet.class, app.PERSISTENCE_UNIT);
		String dr = isOutgoing ? "origin" : "destination";
		Equal sid = new Equal(dr+".substationId",app.getUser().getEmployee().getSubstation().getSubstationId());
		if(isOutgoing){
			container.addContainerFilter(sid);
		} else{
			Equal statusLoaded = new Equal("loadingsheetStatus.loadingsheetStatusId", Constants.LOADINGSHEET_STATUS_LOADED);
			Equal statusDelivered = new Equal("loadingsheetStatus.loadingsheetStatusId", Constants.LOADINGSHEET_STATUS_DELIVERED);
			container.addContainerFilter(new And(sid, new Or(statusLoaded, statusDelivered)));
		}
		if(date.getValue() != null){
    		try{
    			Date start = app.getStartOfADay((Date)date.getValue());
    			Date end = app.getEndOfADay((Date)date.getValue());
    			Between dateEqual = new Between("date", start, end);
    			container.addContainerFilter(dateEqual);
	    	} catch (Exception e) {
	    		app.showNotification("Invalid Input: Please ensure that the input is a valid date.");
	    		return;
			}
    	} else {
    		Date start = app.getStartOfADay(new Date());
    		Date end = app.getEndOfADay(new Date());
    		Between dateEqual = new Between("date", start, end);
			container.addContainerFilter(dateEqual);
    	}
		loadingsheetTable.setContainerDataSource(container);
		loadingsheetTable.setVisibleColumns(columnsLoadingsheetTable);
	}
	
	private void addLoadingsheetWindow(){
		form = new LoadingsheetForm(app, this, "Create loadingsheet", false);
		form.initForm();
		form.setVisibleItemProperties(columnsLoadingsheetForm);
    	
		Window editWindow = new Window();
    	editWindow.center();
    	editWindow.setModal(true);
		VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
    	verticalLayout.addComponent(form);
    	getApplication().getMainWindow().addWindow(editWindow);
	}
	
	private void editLoadingsheetWindow(){
		if(loadingsheetTable.getValue() != null){
			form = new LoadingsheetForm(app, this, "Edit loadingsheet", true);
			Loadingsheet loadingsheet = app.em.find(Loadingsheet.class, loadingsheetTable.getValue());
			app.em.refresh(loadingsheet);
			form.bean = loadingsheet;
			BeanItem<Loadingsheet> beanItem = new BeanItem<Loadingsheet>(loadingsheet);
	    	form.setItemDataSource(beanItem);
	    	form.setVisibleItemProperties(columnsLoadingsheetForm);
	    	form.fieldFactory.routeTime.setValue(loadingsheet.getRouteTime().getRouteTimeId());
	    	form.fieldFactory.origin.setValue(loadingsheet.getOrigin().getSubstationId());
	    	form.fieldFactory.destination.setValue(loadingsheet.getDestination().getSubstationId());
	    	form.fieldFactory.bus.setValue(loadingsheet.getBus().getBusId());
	    	form.fieldFactory.driver.setValue(loadingsheet.getDriver().getEmployeeId());
	    	form.fieldFactory.conductor.setValue(loadingsheet.getConductor().getEmployeeId());
	    	
	    	int status = loadingsheet.getLoadingsheetStatus().getLoadingsheetStatusId(); 
	    	Boolean isNew = status == Constants.LOADINGSHEET_STATUS_NEW;
	    	Boolean isEdited = status == Constants.LOADINGSHEET_STATUS_EDITED;
	    	if(isNew | isEdited) {
	    		form.save.setVisible(true);
	    		form.fieldFactory.origin.setEnabled(false);
	    	}
	    	else {
	    		form.fieldFactory.bus.setEnabled(false);
	    		form.fieldFactory.conductor.setEnabled(false);
	    		form.fieldFactory.driver.setEnabled(false);
	    		form.fieldFactory.origin.setEnabled(false);
	    		form.save.setVisible(false);
	    	}
	    	form.fieldFactory.routeTime.setEnabled(false);
	    	form.fieldFactory.destination.setEnabled(false);
	    	
	    	Window editWindow = new Window();
	    	editWindow.center();
	    	editWindow.setModal(true);
			VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
			verticalLayout.setMargin(true);
	        verticalLayout.setSpacing(true);
			verticalLayout.setSizeUndefined();
	    	verticalLayout.addComponent(form);
	    	getApplication().getMainWindow().addWindow(editWindow);
		}
	}
	
	private Button saveLoadingsheetButton(){
		return new Button("Save", new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				handleSaveLoadingsheet();
				event.getButton().setEnabled(true);
			}
		});
	}
	
	private void handleSaveLoadingsheet(){
		EntityManager em = app.em;
		try{
			if(loadedParcelTable.getContainerDataSource().size() > 0) {
				em.getTransaction().begin();
				
				BeanItemContainer<Parcel> loadedParcelsContainer = (BeanItemContainer<Parcel>) loadedParcelTable.getContainerDataSource();
				for (Parcel p : loadedParcelsContainer.getItemIds()) {
					Parcel p2 = em.find(Parcel.class, p.getParcelId());
					Loadingsheet ls = em.find(Loadingsheet.class, p.getLoadingsheet().getLoadingsheetId());
					em.refresh(p2);
					if(p2.getLoadingsheet() == null) {  
						if(p2.getParcelStatus().getParcelStatusId() != Constants.PARCEL_STATUS_CANCELLED){
							p2.setLoadingsheet(ls);
							ParcelStatus ps = em.find(ParcelStatus.class, Constants.PARCEL_STATUS_LOADED);
							p2.setParcelStatus(ps);
							em.merge(p2);
							
							p.setLoadingsheet(ls);
							p.setParcelStatus(ps);
							
							ParcelAction parcelAction = em.find(ParcelAction.class, Constants.PARCEL_ACTION_LOAD);
							saveParcelHistory(em, p2, app.getUser(), parcelAction, "Loadingsheet nr: "+ selectedLoadingsheet);
						} else {
							loadedParcelsContainer.removeItem(p);
						}
					}
				}
				BeanItemContainer<Parcel> notLoadedParcelsContainer = (BeanItemContainer<Parcel>) notLoadedParcelTable.getContainerDataSource();
				for (Parcel p : notLoadedParcelsContainer.getItemIds()) {
					Parcel p2 = em.find(Parcel.class, p.getParcelId());
					if(p2.getLoadingsheet() != null){
						p2.setLoadingsheet(null);
						ParcelStatus ps = em.find(ParcelStatus.class, Constants.PARCEL_STATUS_UNLOADED);
						p2.setParcelStatus(ps);
						em.merge(p2);
						
						p.setLoadingsheet(null);
						p.setParcelStatus(ps);
						
						ParcelAction parcelAction = em.find(ParcelAction.class, Constants.PARCEL_ACTION_UNLOAD);
						saveParcelHistory(em, p2, app.getUser(), parcelAction, "Unloaded");
					} else if(p2.getParcelStatus().getParcelStatusId() == Constants.PARCEL_STATUS_CANCELLED){
						notLoadedParcelsContainer.removeItem(p);
					}
				}			
				loadedParcelTable.setContainerDataSource(loadedParcelsContainer);
				loadedParcelTable.setVisibleColumns(columnsLoadedParcelTable);
				notLoadedParcelTable.setContainerDataSource(notLoadedParcelsContainer);
				notLoadedParcelTable.setVisibleColumns(columnsNotLoadedParcelTable);
				
				LoadingsheetStatus loadingsheetStatus = em.find(LoadingsheetStatus.class, Constants.LOADINGSHEET_STATUS_LOADED);
				Loadingsheet loadingsheet = em.find(Loadingsheet.class, selectedLoadingsheet);
				loadingsheet.setLoadingsheetStatus(loadingsheetStatus);
				em.merge(loadingsheet);
				
				LoadingsheetAction loadingsheetAction = em.find(LoadingsheetAction.class, Constants.LOADINGSHEET_ACTION_LOAD);
				saveLoadingsheetHistory(em, loadingsheet, loadingsheetAction, "loaded");
				
				em.getTransaction().commit();
				app.showNotification(Constants.SUCCESSFULLY_SAVED_MESSAGE);
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
		}
	}
	
	private void handleSaveDeliverLoadingsheet(){
		EntityManager em = app.em;
		try{
			if(loadedParcelTable.getContainerDataSource().size() > 0) {
				em.getTransaction().begin();
				
				BeanItemContainer<Parcel> loadedParcelsContainer = (BeanItemContainer<Parcel>) loadedParcelTable.getContainerDataSource();
				for (Parcel p : loadedParcelsContainer.getItemIds()) {
					Parcel p2 = em.find(Parcel.class, p.getParcelId());
					ParcelStatus ps = em.find(ParcelStatus.class, Constants.PARCEL_STATUS_DELIVERED);
					p2.setParcelStatus(ps);
					em.merge(p2);
					
					ParcelAction parcelAction = em.find(ParcelAction.class, Constants.PARCEL_ACTION_DELIVER);
					saveParcelHistory(em, p2, app.getUser(), parcelAction, "delivered");
				}
							
				loadedParcelTable.setContainerDataSource(loadedParcelsContainer);
				loadedParcelTable.setVisibleColumns(columnsLoadedParcelTable);
				
				LoadingsheetStatus loadingsheetStatus = em.find(LoadingsheetStatus.class, Constants.LOADINGSHEET_STATUS_DELIVERED);
				Loadingsheet loadingsheet = em.find(Loadingsheet.class, selectedLoadingsheet);
				loadingsheet.setLoadingsheetStatus(loadingsheetStatus);
				em.merge(loadingsheet);
				
				LoadingsheetAction loadingsheetAction = em.find(LoadingsheetAction.class, Constants.LOADINGSHEET_ACTION_DELIVER);
				saveLoadingsheetHistory(em, loadingsheet, loadingsheetAction, "delivered");
				
				em.getTransaction().commit();
				app.showNotification("Loadingsheet is set to delivered.");
				searchLoadingsheet();
			}
		} catch (Exception e) {
			app.showNotification("Oooopss something whent wrong !!..");
			em.getTransaction().rollback();
		}
	}
	
	private void saveLoadingsheetHistory(EntityManager em, Loadingsheet loadingsheet, LoadingsheetAction loadingsheetAction, String desc){
		LoadingsheetHistory loadingsheetHistory = new LoadingsheetHistory();
		loadingsheetHistory.setLoadingsheet(loadingsheet);
		loadingsheetHistory.setDate(new Date());
		loadingsheetHistory.setDescription("Loadingsheet is " + desc);
		loadingsheetHistory.setLoadingsheetAction(loadingsheetAction);
		loadingsheetHistory.setUser(app.getUser());
		em.persist(loadingsheetHistory);
	}
	
	private void deliverParcelWindow(Integer selectedLoadingsheet){
		final Window editWindow = new Window("Deliver parcels");
    	
    	VerticalLayout verticalLayout = (VerticalLayout) editWindow.getContent();
		verticalLayout.setMargin(true);
        verticalLayout.setSpacing(true);
		verticalLayout.setSizeUndefined();
		
		notLoadedParcelsLayout.removeAllComponents();
		loadedParcelsLayout.removeAllComponents();
		
		Button save = new Button("Save");
		save.addStyleName("blueButton");
		save.setDisableOnClick(true);
		save.addListener(new Button.ClickListener() {
				public void buttonClick(ClickEvent event) {
					handleSaveDeliverLoadingsheet();
					event.getButton().setEnabled(true);
				}
			});
		
		Button close = new Button("Close");
		close.addStyleName("grayButton");
		close.addListener(new Button.ClickListener() {
            public void buttonClick(ClickEvent event) {
                Window editWindow = (Window) event.getButton().getParent().getParent().getParent();
            	(editWindow.getParent()).removeWindow(editWindow);
            }
        });
		
		HorizontalLayout buttons = new HorizontalLayout();
		buttons.setSpacing(true);
		buttons.addComponent(save);
		buttons.addComponent(close);
		verticalLayout.addComponent(buttons);
		verticalLayout.setComponentAlignment(buttons, Alignment.BOTTOM_RIGHT);
		
		HorizontalLayout horizontalLayout = new HorizontalLayout();
		horizontalLayout.setSpacing(true);
        
        BeanItemContainer<Parcel> todaysLoadedParcelsContainer = mainLayout.getParcelsByLoadingsheetId("receiverStation", selectedLoadingsheet);
        loadedParcelTable = new ParcelTable(app, "Loaded Parcels", todaysLoadedParcelsContainer, columnsLoadedParcelTable, selectedLoadingsheet);
		
		loadedParcelsLayout.addComponent(loadedParcelTable);
		horizontalLayout.addComponent(loadedParcelsLayout);
		verticalLayout.addComponent(horizontalLayout);
			
		editWindow.center();
    	editWindow.setModal(true);
    	getApplication().getMainWindow().addWindow(editWindow);
	}
	
	private void saveParcelHistory(EntityManager em, Parcel parcel, User user, ParcelAction parcelAction, String desc){ 
		ParcelHistory parcelHistory = new ParcelHistory();
		parcelHistory.setParcel(parcel);
		parcelHistory.setUser(user);
		Date date = new Date();
		parcelHistory.setDate(date);
		parcelHistory.setParcelAction(parcelAction);
		parcelHistory.setDescription(desc);
		em.persist(parcelHistory);
	}
	
	public void showParcelTables(Integer selectedLoadingsheet){
		notLoadedParcelsLayout.removeAllComponents();
		loadedParcelsLayout.removeAllComponents();
		String stationType = isOutgoing ? "senderStation" : "receiverStation";
        BeanItemContainer<Parcel> todaysLoadedParcelsContainer = mainLayout.getParcelsByLoadingsheetId(stationType, selectedLoadingsheet);
        loadedParcelTable = new ParcelTable(app, "Loaded Parcels", todaysLoadedParcelsContainer, columnsLoadedParcelTable, selectedLoadingsheet);
		
		Loadingsheet loadingsheet = app.em.find(Loadingsheet.class, selectedLoadingsheet);
		app.em.refresh(loadingsheet);
		Date yesterday = app.getYesterdaysDateWithoutTime();
		int dateCompare = yesterday.compareTo(loadingsheet.getDate());
		int status = loadingsheet.getLoadingsheetStatus().getLoadingsheetStatusId();
		Boolean newOrEditOrLoaded = status == Constants.LOADINGSHEET_STATUS_NEW | status == Constants.LOADINGSHEET_STATUS_EDITED | status == Constants.LOADINGSHEET_STATUS_LOADED;
        if(isOutgoing && newOrEditOrLoaded && (dateCompare == 0 | dateCompare == -1 ) && currentUser.isPermitted(PermissionsConstants.PERMISSION_LOADINGSHEET_OUTGOING_LOAD)){
        	editBtn.setEnabled(true);
        	saveLoadingsheetBtn.setVisible(true);
        	
        	BeanItemContainer<Parcel> todaysNotLoadedParcelsContainer = getNotLoadedParcels();		
			notLoadedParcelTable = new ParcelTable(app, "Not loaded Parcels", todaysNotLoadedParcelsContainer, columnsNotLoadedParcelTable, 0);
			notLoadedParcelTable.setSelectable(true);
			notLoadedParcelTable.setMultiSelect(true);		
			notLoadedParcelTable.initializeTable(new SourceIs(loadedParcelTable), todaysNotLoadedParcelsContainer);
			
			loadedParcelTable.setSelectable(true);
			loadedParcelTable.setMultiSelect(true);
			loadedParcelTable.initializeTable(new SourceIs(notLoadedParcelTable), todaysLoadedParcelsContainer);
			
			notLoadedParcelsLayout.addComponent(notLoadedParcelTable);
		} else{
			if(isOutgoing)
				editBtn.setEnabled(false);
			saveLoadingsheetBtn.setVisible(false);
		}
		loadedParcelsLayout.addComponent(loadedParcelTable);
    }
	
	public BeanItemContainer<Parcel> getNotLoadedParcels(){
    	BeanItemContainer<Parcel> beanItemContainer = new BeanItemContainer<Parcel>(Parcel.class);
    	int userSubstationId = app.getUser().getEmployee().getSubstation().getSubstationId();
    	Loadingsheet loadingsheet = ((JPAContainerItem<Loadingsheet>) loadingsheetTable.getItem(loadingsheetTable.getValue())).getEntity();
    	
    	String query = "select p.* from parcel p, parcel_detail pd where p.parcelDetail = pd.parcelDetailId " +
    			"and pd.senderSubstation = "+ userSubstationId +" and pd.receiverSubstation in " +
    			"( select substationId from substation where substationId != "+ userSubstationId +" and substationId in ( select substation from route_detail rd where route = "+ loadingsheet.getRouteTime().getRoute().getRouteId() +")) " +
    			"and (p.parcelStatus = "+ Constants.PARCEL_STATUS_NEW +" or p.parcelStatus = "+ Constants.PARCEL_STATUS_EDITED +" or p.parcelStatus = "+ Constants.PARCEL_STATUS_UNLOADED +" or p.parcelStatus = "+ Constants.PARCEL_STATUS_UNDELIVERED +")";
    	String query2 = " select p.* " +
    			" from parcel p, parcel_detail pd, substation s, route_detail rd " +
    			" where p.parcelDetail = pd.parcelDetailId and pd.senderSubstation = "+ userSubstationId +" and pd.receiverSubstation = s.substationId " +
    			" and s.substationId != "+ userSubstationId +" and s.substationId = rd.substation and route = "+ loadingsheet.getRouteTime().getRoute().getRouteId() +" " +
    			" and p.parcelStatus in ( "+ Constants.PARCEL_STATUS_NEW +", "+ Constants.PARCEL_STATUS_EDITED +", "+ Constants.PARCEL_STATUS_UNLOADED +", "+ Constants.PARCEL_STATUS_UNDELIVERED +" ) ";
    	List<Parcel> ps = app.em.createNativeQuery(query, Parcel.class).getResultList();
    	for (Parcel parcel : ps) {
    		beanItemContainer.addBean(parcel);
		}
		return beanItemContainer;
    }
	
	public Equal equalUserStationId(String stationType){
    	return new Equal("parcelDetail."+stationType+".stationId",app.getUser().getEmployee().getStation().getStationId());
    }
    
    public Equal equalUserSubstationId(String substationType){
    	return new Equal("parcelDetail."+substationType+".substationId",app.getUser().getEmployee().getSubstation().getSubstationId());
    }
    
    public Equal equalUserSubstationId(String substationType, Integer substationId){
    	return new Equal("parcelDetail."+substationType+".substationId", substationId);
    }
}